﻿using Microsoft.Extensions.FileProviders;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;

namespace Orchid.Blazor.Hosting.Repositories
{
    /// <summary>
    /// 基于 ZIP 压缩文件的 <inheritdoc cref="WebRepository"/>
    /// </summary>
    public class WebArchiveRepository : WebRepository
    {
        private string _rootPath = null;
        private List<ZipArchiveFile> _files = new List<ZipArchiveFile>();

        /// <summary>
        /// 文件。
        /// </summary>
        public FileInfo File { get; }

        /// <inheritdoc/>
        public override string Name { get; }

        /// <summary>
        /// <inheritdoc cref="WebArchiveRepository"/>
        /// </summary>
        /// <param name="file">文件。</param>
        public WebArchiveRepository(FileInfo file)
        {
            this.File = file ?? throw new ArgumentNullException(nameof(file));
            this.Path = this.File.FullName;
            this.Name = System.IO.Path.GetFileNameWithoutExtension(this.File.Name);

            using (var _archive = new ZipArchive(this.File.OpenRead(), ZipArchiveMode.Read))
            {
                var indexFile = _archive.Entries.Where(x => string.Equals(x.Name, DefaultFileName, StringComparison.OrdinalIgnoreCase)).OrderBy(x => x.FullName.Length).FirstOrDefault();
                var index = indexFile.FullName.LastIndexOf('/');
                if (index < 0) _rootPath = string.Empty;
                else _rootPath = indexFile.FullName.Substring(0, index + 1);

                foreach (var entry in _archive.Entries) _files.Add(new ZipArchiveFile(entry));
            }
        }
        /// <inheritdoc/>
        protected override IFileInfo GetFile(string subpath)
        {
            subpath = subpath?.TrimEnd().TrimStart(' ', '/');
            if (string.IsNullOrEmpty(subpath)) return new NotFoundFileInfo(subpath);
            var path = _rootPath + subpath;
            var file = _files.FirstOrDefault(x => string.Equals(x.FullName, path, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(x.Name));
            if (file == null) return new NotFoundFileInfo(path);
            return file;
        }
        class ZipArchiveFile : MarshalByRefObject, IFileInfo
        {
            private byte[] _buff;

            public string Name { get; }
            public string FullName { get; }
            public bool Exists { get; } = true;
            public bool IsDirectory { get; } = false;
            public long Length { get; }
            public string PhysicalPath { get; }
            public DateTimeOffset LastModified { get; }

            public ZipArchiveFile(ZipArchiveEntry entry)
            {
                if (entry == null) throw new ArgumentNullException(nameof(entry));
                this.Name = entry.Name;
                this.FullName = entry.FullName;
                this.Length = entry.Length;
                this.LastModified = entry.LastWriteTime;

                _buff = new byte[this.Length];
                entry.Open().Read(_buff, 0, _buff.Length);
            }

            public Stream CreateReadStream() => new MemoryStream(_buff);
        }

        /// <summary>
        /// 获取网站仓库集。
        /// </summary>
        /// <param name="directory">目录。</param>
        /// <returns>获取到的网站仓库集合。</returns>
        public static IEnumerable<WebArchiveRepository> GetRepostories(DirectoryInfo directory)
        {
            var res = new List<WebArchiveRepository>();
            if (directory == null) return res;
            if (!directory.Exists) return res;

            var files = directory.GetFiles("*.zip");
            foreach (var file in files) res.Add(new WebArchiveRepository(file));

            return res;
        }
    }
}
